26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
52 #pragma package(smart_init)
62 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
63 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
64 int IncrementalDigitsIn,
int SignallerMaxSpeedIn): RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
65 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
66 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
67 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
78 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
79 AnsiString(TrainModeIn));
123 for(
int x = 0; x < 4; x++)
132 for(
int x = 0; x < 4; x++)
141 for(
int x = 0; x < 4; x++)
146 for(
int x = 0; x < 4; x++)
150 for(
int x = 0; x < 3; x++)
187 for(
int x = 0; x < 4; x++)
232 throw Exception(
"Error in attempting to delete FrontCodePtr");
236 for(
int x = 0; x < 4; x++)
240 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
245 for(
int x = 0; x < 4; x++)
249 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
278 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
340 bool TempDerail =
false;
384 else if((NextElementPosition > -1) && (NextEntryPos > -1))
450 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
461 for(
int x = 0; x < 4; x++)
468 for(
int x = 0; x < 4; x++)
700 if((random(RandRange)) == 0)
715 int LockedVectorNumber;
928 if(BufferLocation ==
"")
931 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
995 int NextElementPosition, NextEntryPos;
1019 NextElementPosition = -1;
1023 if((NextElementPosition > -1) && (NextEntryPos > -1))
1138 AnsiString StationName;
1149 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1163 if((NextElementPosition > -1) && (NextEntryPos > -1))
1290 if(NextElementPosition > -1)
1329 AnsiString Loc =
"";
1330 bool LocNamed =
false;
1359 Loc =
"outside railway";
1385 NextElementPosition = -1;
1398 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1417 if((NextElementPosition > -1) && (NextEntryPos > -1))
1456 FirstPair.second).
GetELink() == TempELink))
1461 SecondPair.second).
GetELink() == TempELink))
1476 FirstPair.second).
GetELink() == TempELink))
1481 SecondPair.second).
GetELink() == TempELink))
1496 FirstPair.second).
GetELink() == TempELink))
1501 SecondPair.second).
GetELink() == TempELink))
1534 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1537 int NewLastElement = 0, NewLastExitPos = 0;
1551 if(NewLastElement == -1)
1554 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1557 if(NewLastExitPos == -1)
1559 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1561 LastElement = NewLastElement;
1562 LastExitPos = NewLastExitPos;
1565 if(CumDistance < 1200)
1571 int FirstDistance = 0;
1572 if(CumDistance >= 1200)
1573 FirstDistance = 100;
1575 FirstDistance = 1200 - CumDistance;
1576 if(FirstDistance < 100)
1577 FirstDistance = 100;
1602 if(VectorIT->RouteNumber == RouteNumber)
1647 LockedVectorNumber)))
1808 for(
int x = 0; x < 4; x++)
1815 for(
int x = 0; x < 4; x++)
1842 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
1847 if(OtherTrainEntryPos == -1)
1849 throw Exception(
"Error - OtherTrainEntryPos not set");
1868 int OtherTrainID = -1;
1869 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
1964 bool StopRequired =
false;
1977 int NextElementEntryPos = -1;
1978 int NextElementExitPos = -1;
1979 bool TrainOnNextElement =
false;
1980 bool StopSignalAtNextElement =
false;
1981 if(ForwardConnection)
1989 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
1992 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2048 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2262 if(Code.Length() != 4)
2264 for(
int x = 1; x < 5; x++)
2271 for(
int x = 0; x < 4; x++)
2419 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2431 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2442 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2451 TRect SourceRect, DestRect;
2453 DestRect.init(0, 0, 8, 8);
2456 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2458 TempGraphic->PixelFormat = pf8bit;
2459 TempGraphic->Width = 16;
2460 TempGraphic->Height = 16;
2466 TempGraphic->Transparent =
true;
2470 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2471 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2475 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2481 else if(TempElement.
SpeedTag == 89)
2483 else if(TempElement.
SpeedTag == 90)
2485 else if(TempElement.
SpeedTag == 91)
2487 else if(TempElement.
SpeedTag == 92)
2489 else if(TempElement.
SpeedTag == 93)
2491 else if(TempElement.
SpeedTag == 94)
2493 else if(TempElement.
SpeedTag == 95)
2495 TempGraphic->Transparent =
true;
2499 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2500 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2502 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2509 for(
int x = 0; x < 40; x++)
2524 TempGraphic->Transparent =
true;
2528 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2529 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2531 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2545 TempGraphic->Transparent =
true;
2549 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2550 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2553 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2555 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2560 TempGraphic->Transparent =
true;
2564 int BDVectorPos = -1;
2573 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2578 TempGraphic->Transparent =
true;
2582 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2583 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2585 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2591 TempGraphic->Transparent =
true;
2595 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2596 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2598 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2864 throw Exception(
"Error, same train on two different bridge tracks");
2910 AnsiString(EntryPos) +
"," +
HeadCode);
2928 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
2943 AnsiString(EntryPos) +
"," +
HeadCode);
2952 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
2979 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
2980 int LockedVectorNumber;
2992 TRect SourceRect, DestRect;
2993 DestRect.init(0, 0, 8, 8);
3000 int FirstELink, SecondELink = -1;
3003 if(RoutePair2.first > -1)
3010 if(SecondELink == -1)
3012 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3017 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3027 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3028 DestGraphic->PixelFormat = pf8bit;
3029 DestGraphic->Width = 8;
3030 DestGraphic->Height = 8;
3031 DestGraphic->Transparent =
true;
3034 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3043 PrefDirElement, LockedVectorNumber))
3058 if(ElementEntryPos > 1)
3080 AnsiString(EntryPos) +
"," +
HeadCode);
3082 bool WrongRoute =
false;
3107 int LinkNumber = TrackElement.
Link[EntryPos];
3108 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3113 bool LogActionErrorCalled =
false;
3122 LogActionErrorCalled =
true;
3138 else if(LinkNumber == 3)
3145 LogActionErrorCalled =
true;
3161 else if(LinkNumber == 7)
3168 LogActionErrorCalled =
true;
3184 else if(LinkNumber == 9)
3191 LogActionErrorCalled =
true;
3222 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3227 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3237 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3242 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3251 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3269 bool ColourError =
false, ColourError2 =
false;
3273 ColourError2 =
true;
3274 for(
int x = 0; x < 4; x++)
3278 ColourError2 =
true;
3283 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3288 for(
int x = 0; x < 4; x++)
3375 AnsiString(EntryPos) +
"," +
HeadCode);
3376 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3377 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3378 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3379 TrainInFrontInSignallerModeFlag =
false;
3380 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3381 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3382 bool SignallerStopRequired =
false;
3393 if(CurrentTrackVectorPosition > -1)
3397 if((EntryPos == 0) || (EntryPos == 2))
3410 else if(EntryPos == 1)
3434 EntryHalfLength = CurrentElementHalfLength;
3439 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3443 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3489 FrontElementMaxSpeed = LimitingSpeed;
3520 double ExitSpeedAtMaxBraking;
3525 ExitSpeedAtMaxBraking = 0;
3535 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3537 SpeedToUse = ExitSpeedAtMaxBraking;
3541 SpeedToUse = LimitingSpeed;
3556 RedSignalFlag =
false;
3557 BuffersFlag =
false;
3558 StationFlag =
false;
3559 BuffersOrContinuationNowFlag =
false;
3560 ContinuationNextFlag =
false;
3563 CumulativeLength += (2 * CurrentElementHalfLength);
3566 SignallerStopRequired =
true;
3588 bool StopRequired =
false;
3602 StationFlag =
false;
3609 BuffersOrContinuationNowFlag =
true;
3611 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3615 if((EntryPos == 0) || (EntryPos == 2))
3629 if(NextTrackVectorPosition > -1)
3634 if((NextEntryPos == 0) || (NextEntryPos == 2))
3647 else if(NextEntryPos == 1)
3660 if(NextEntryPos > 1)
3674 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
3685 RedSignalFlag =
true;
3704 TrainInFrontInSignallerModeFlag =
true;
3728 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
3740 double MaxHalfSpeed;
3744 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
3745 MaxHalfSpeed = FrontElementMaxSpeed;
3747 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
3754 bool HalfSpeedLimited =
false;
3758 HalfSpeedLimited =
true;
3783 if(HalfSpeedLimited)
3804 if(SignallerStopRequired)
3820 int TempMaxExitSpeed;
3823 if(MaxExitSpeedAtHalfBrakingSquared < 10)
3824 MaxExitSpeedAtHalfBraking = 0;
3826 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
3829 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
3830 TempMaxExitSpeed = FrontElementMaxSpeed;
3832 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
3842 if(ExitSpeedHalfSquared < 10)
3848 if(ExitSpeedFullSquared < 10)
3912 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
3913 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
3933 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
3934 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
3944 if(!BuffersOrContinuationNowFlag)
3946 if(NextSpeedLimit < LimitingSpeed)
3947 LimitingSpeed = NextSpeedLimit;
3950 int TempMaxExitSpeed;
3954 if(MaxExitSpeedAtHalfBrakingSquared < 10)
3955 MaxExitSpeedAtHalfBraking = 0;
3957 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
3958 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
3959 TempMaxExitSpeed = FrontElementMaxSpeed;
3961 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
3969 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
3978 if(!BuffersOrContinuationNowFlag)
3980 CurrentTrackVectorPosition = NextTrackVectorPosition;
3981 EntryPos = NextEntryPos;
3982 CurrentElementHalfLength = NextElementHalfLength;
3985 ContinuationNextFlag =
true;
3989 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4009 if(ExitSpeedHalfSquared < 10)
4015 if(ExitSpeedFullSquared < 10)
4069 double DeltaExitTimeToMaxInSecs;
4070 double DistanceToMax;
4079 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4081 DistanceToMax = EntryHalfLength;
4084 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4085 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4098 double DeltaExitTimeToMaxInSecs;
4099 double DistanceToMax;
4108 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4110 DistanceToMax = EntryHalfLength / 2;
4113 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4114 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4125 if(ExitSpeedHalfSquared < 10)
4131 if(ExitSpeedFullSquared < 10)
4146 if((EntryPos == 0) || (EntryPos == 2))
4160 if(NextTrackVectorPosition > -1)
4162 int NextElementLength;
4163 if(NextEntryPos > 1)
4171 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4307 if((Ptr->Command ==
"cdt") || (Ptr->FormatType ==
Repeat))
4311 if((Ptr->ArrivalTime > TDateTime(-1)) && (Ptr->LocationName == Name))
4320 if((Ptr->EventTime > TDateTime(-1)) && (Ptr->LocationName == Name) && (Ptr->Command ==
"pas"))
4345 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4363 CurrentTrackVectorPosition).
Attribute != 4))
4399 if((EntryPos == 0) || (EntryPos == 2))
4413 CurrentTrackVectorPosition = NextTrackVectorPosition;
4414 EntryPos = NextEntryPos;
4438 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4462 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4463 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4464 int RouteStartPosition;
4466 int PlatformPosition;
4468 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4507 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
4510 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
4556 if(!PlatformFoundFlag)
4557 PlatformPosition = CurrentTrackVectorPosition;
4559 PlatformFoundFlag =
true;
4575 if((EntryPos == 0) || (EntryPos == 2))
4610 if(ElementNumber < 2)
4611 SkipRouteCheck =
true;
4613 SkipRouteCheck =
false;
4614 if(ElementNumber == 1)
4616 RouteStartPosition = CurrentTrackVectorPosition;
4626 if(ElementNumber > 1)
4629 RouteOrPartRouteSet =
true;
4631 RouteOrPartRouteSet =
false;
4633 if(!SkipRouteCheck && !RouteOrPartRouteSet)
4640 int ExitLink = CurrentTrackElement.
Link[ExitPos];
4641 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
4653 Distance += CurrentTrackElement.
Length01;
4655 Distance += CurrentTrackElement.
Length23;
4656 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
4657 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
4658 CurrentTrackVectorPosition = NextTrackVectorPosition;
4659 EntryPos = NextEntryPos;
4696 return RepeatHeadCode;
4717 bool FrontValid =
false, RearValid =
false;
4718 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
4722 TrainToBeJoinedBy = NULL;
4736 int TrainToBeJoinedByID = -1;
4757 if((TrainToBeJoinedByID < 0) && RearValid)
4776 if(TrainToBeJoinedByID < 0)
4778 TrainToBeJoinedBy = NULL;
4783 if(!TrainToBeJoinedBy->
Stopped())
4785 TrainToBeJoinedBy = NULL;
4796 TDateTime TimetableNonRepeatTime,
bool Warning)
4831 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
4832 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
4833 int IntMinsLate = 0;
4837 ActionLog =
" arrived at ";
4845 ActionLog =
" terminated at ";
4849 ActionLog =
" departed from ";
4850 if(ActionType ==
Pass)
4851 ActionLog =
" passed ";
4853 ActionLog =
" created at ";
4854 if(ActionType ==
Enter)
4855 ActionLog =
" entered railway at ";
4856 if(ActionType ==
Leave)
4857 ActionLog =
" left railway at ";
4859 ActionLog =
" split from front to ";
4861 ActionLog =
" split from rear to ";
4863 ActionLog =
" joined by ";
4865 ActionLog =
" changed direction at ";
4867 ActionLog =
" became new service ";
4869 ActionLog =
" taken under signaller control at ";
4871 ActionLog =
" restored to timetable control at ";
4875 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
4877 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
4879 ActionLog =
" REMOVED FROM RAILWAY at ";
4882 ActionLog =
" received signaller authority to proceed";
4884 ActionLog =
" received signaller authority to step forward";
4886 ActionLog =
" changed direction under signaller control at ";
4888 ActionLog =
" received signaller authority to pass red signal";
4890 ActionLog =
" received signaller instruction to stop";
4892 ActionLog =
" stopped on signaller instruction ";
4894 ActionLog =
" joined under signaller control by ";
4896 ActionLog =
" suffered an onboard power failure at ";
4898 ActionLog =
" failure repaired at ";
4900 ActionLog =
" left railway under signaller control at ";
4901 if(OtherHeadCode !=
"")
4902 OtherHeadCode +=
" at ";
4908 WarningBaseLog =
HeadCode + ActionLog + OtherHeadCode + LocationName;
4914 bool TimePerformance =
true;
4922 TimePerformance =
false;
4926 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
4936 IntMinsLate = int(ceil(MinsLate));
4940 IntMinsLate = int(floor(MinsLate));
4942 if(IntMinsLate == 0)
4944 PerfLog =
" on time";
4946 else if(IntMinsLate == 1)
4947 PerfLog =
" 1 minute late";
4948 else if(IntMinsLate == -1)
4949 PerfLog =
" 1 minute early";
4950 else if(IntMinsLate > 1)
4951 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
4952 else if(IntMinsLate < -1)
4954 int PosIntMinsLate = -IntMinsLate;
4955 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
4957 if(LocationName.Pos(
'-') > 0)
4959 PerfLog =
"," + PerfLog;
4972 if((ActionType ==
Arrive) && (IntMinsLate == 0))
4976 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
4981 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
4986 else if((ActionType ==
Pass) && (IntMinsLate == 0))
4990 else if((ActionType ==
Pass) && (IntMinsLate > 0))
4995 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5000 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5004 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5023 AnsiString LocName =
"";
5087 if(LocationName ==
"")
5089 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5090 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5091 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5095 if(LocationName !=
"")
5103 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5108 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5122 int LeadPosA = FirstNamedElementPos;
5123 int LeadPosB = FirstNamedLinkedElementPos;
5124 int LeadPosC = SecondNamedElementPos;
5125 int LeadPosD = SecondNamedLinkedElementPos;
5127 int LeadNumAtLoc = 0;
5136 if(LeadNumAtLoc < 4)
5140 SecondNamedLinkedElementPos))
5142 FirstNamedElementPos = LeadPosA;
5143 FirstNamedLinkedElementPos = LeadPosB;
5144 SecondNamedElementPos = LeadPosC;
5145 SecondNamedLinkedElementPos = LeadPosD;
5149 int MidNumAtLoc = 0;
5158 if(LeadNumAtLoc > MidNumAtLoc)
5161 FirstNamedElementPos = LeadPosA;
5162 FirstNamedLinkedElementPos = LeadPosB;
5163 SecondNamedElementPos = LeadPosC;
5164 SecondNamedLinkedElementPos = LeadPosD;
5177 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5186 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5187 FrontTrainRearPosition = FirstNamedElementPos;
5188 RearTrainFrontPosition = SecondNamedElementPos;
5189 RearTrainRearPosition = SecondNamedLinkedElementPos;
5193 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5194 FrontTrainRearPosition = SecondNamedElementPos;
5195 RearTrainFrontPosition = FirstNamedElementPos;
5196 RearTrainRearPosition = FirstNamedLinkedElementPos;
5203 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5204 FrontTrainRearPosition = SecondNamedElementPos;
5205 RearTrainFrontPosition = FirstNamedElementPos;
5206 RearTrainRearPosition = FirstNamedLinkedElementPos;
5210 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5211 FrontTrainRearPosition = FirstNamedElementPos;
5212 RearTrainFrontPosition = SecondNamedElementPos;
5213 RearTrainRearPosition = SecondNamedLinkedElementPos;
5216 RearTrainExitPos = -1;
5217 for(
int x = 0; x < 4; x++)
5221 RearTrainExitPos = x;
5225 if(RearTrainExitPos == -1)
5226 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5228 FrontTrainExitPos = -1;
5229 for(
int x = 0; x < 4; x++)
5233 FrontTrainExitPos = x;
5237 if(FrontTrainExitPos == -1)
5238 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5241 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5246 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5260 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5265 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5266 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5267 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5363 if(LocationName ==
"")
5365 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5366 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5367 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5371 if(LocationName !=
"")
5378 SecondNamedLinkedElementPos))
5382 SecondNamedLinkedElementPos))
5396 int LeadPosA = FirstNamedElementPos;
5397 int LeadPosB = FirstNamedLinkedElementPos;
5398 int LeadPosC = SecondNamedElementPos;
5399 int LeadPosD = SecondNamedLinkedElementPos;
5401 int LeadNumAtLoc = 0;
5410 if(LeadNumAtLoc < 4)
5414 SecondNamedLinkedElementPos))
5416 FirstNamedElementPos = LeadPosA;
5417 FirstNamedLinkedElementPos = LeadPosB;
5418 SecondNamedElementPos = LeadPosC;
5419 SecondNamedLinkedElementPos = LeadPosD;
5423 int MidNumAtLoc = 0;
5432 if(LeadNumAtLoc > MidNumAtLoc)
5435 FirstNamedElementPos = LeadPosA;
5436 FirstNamedLinkedElementPos = LeadPosB;
5437 SecondNamedElementPos = LeadPosC;
5438 SecondNamedLinkedElementPos = LeadPosD;
5451 throw Exception(
"Error - LocationName not set in RearTrainSplit");
5460 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5461 FrontTrainRearPosition = FirstNamedElementPos;
5462 RearTrainFrontPosition = SecondNamedElementPos;
5463 RearTrainRearPosition = SecondNamedLinkedElementPos;
5467 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5468 FrontTrainRearPosition = SecondNamedElementPos;
5469 RearTrainFrontPosition = FirstNamedElementPos;
5470 RearTrainRearPosition = FirstNamedLinkedElementPos;
5477 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5478 FrontTrainRearPosition = SecondNamedElementPos;
5479 RearTrainFrontPosition = FirstNamedElementPos;
5480 RearTrainRearPosition = FirstNamedLinkedElementPos;
5484 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5485 FrontTrainRearPosition = FirstNamedElementPos;
5486 RearTrainFrontPosition = SecondNamedElementPos;
5487 RearTrainRearPosition = SecondNamedLinkedElementPos;
5490 RearTrainExitPos = -1;
5491 for(
int x = 0; x < 4; x++)
5495 RearTrainExitPos = x;
5499 if(RearTrainExitPos == -1)
5500 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
5501 FrontTrainExitPos = -1;
5502 for(
int x = 0; x < 4; x++)
5506 FrontTrainExitPos = x;
5510 if(FrontTrainExitPos == -1)
5511 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
5514 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5519 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5533 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5538 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5539 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5540 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5677 TTrain *TrainToBeJoinedBy;
5708 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
5710 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
5765 int RouteNumber = -1;
5871 for(
int x = 0; x < IncNum; x++)
5902 else if(Ptr->
Command ==
"jbo")
5913 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
5919 bool IncludeFER =
false;
5925 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
5930 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
5941 else if(Ptr->
Command ==
"Fjo")
5947 else if(Ptr->
Command ==
"Frh")
5957 else if(Ptr->
Command ==
"Frh-sh")
6008 else if(Ptr->
Command ==
"jbo")
6013 else if(Ptr->
Command ==
"cdt")
6021 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6384 int RouteNumber = -1;
6419 ",FloatingLabelNextString" +
"," +
HeadCode);
6420 AnsiString RetStr =
"", LocationName =
"";
6424 throw Exception(
"Error - start entry in FloatingLabelNextString");
6464 else if(Ptr->
Command ==
"Fns")
6470 else if(Ptr->
Command ==
"F-nshs")
6501 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6503 else if(Ptr->
Command ==
"Frh")
6505 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6507 else if(Ptr->
Command ==
"Fer")
6511 else if(Ptr->
Command ==
"Fjo")
6516 else if(Ptr->
Command ==
"jbo")
6521 else if(Ptr->
Command ==
"fsp")
6526 else if(Ptr->
Command ==
"rsp")
6531 else if(Ptr->
Command ==
"cdt")
6544 + AnsiString(RptNum) +
",CheckNewServiceDepartureTime," +
HeadCode);
6545 AnsiString DepTime =
"", EventTime =
"";
6546 bool CDTFlag =
false;
6550 if(AVI->Command ==
"cdt")
6555 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
6558 RetStr +=
"\nNew service splits at " + EventTime;
6562 if(AVI->Command ==
"jbo")
6565 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
6569 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
6574 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
6578 RetStr +=
"\nNew service departs at " + DepTime;
6594 ",FloatingTimetableString" +
"," +
HeadCode);
6595 AnsiString RetStr =
"", PartStr =
"";
6601 throw Exception(
"Error - start entry in FloatingTimetableString");
6604 bool FirstPass =
true;
6615 AnsiString TrainLoc =
"";
6653 AnsiString TrainLoc =
"";
6681 else if(Ptr->
Command ==
"Fns")
6687 else if(Ptr->
Command ==
"F-nshs")
6720 else if(Ptr->
Command ==
"Frh")
6724 else if(Ptr->
Command ==
"Fer")
6728 else if(Ptr->
Command ==
"Fjo")
6733 else if(Ptr->
Command ==
"jbo")
6738 else if(Ptr->
Command ==
"fsp")
6743 else if(Ptr->
Command ==
"rsp")
6748 else if(Ptr->
Command ==
"cdt")
6753 RetStr = RetStr +
'\n' + PartStr;
6766 RetStr =
"Timetable finished";
6768 RetStr =
"No timetable";
6894 bool ForwardHeadCode;
6898 ForwardHeadCode =
true;
6903 ForwardHeadCode =
false;
7036 if(ColourNumber == 0)
7038 else if(ColourNumber == 1)
7040 else if(ColourNumber == 2)
7042 else if(ColourNumber == 3)
7044 else if(ColourNumber == 4)
7046 else if(ColourNumber == 5)
7048 else if(ColourNumber == 6)
7050 else if(ColourNumber == 7)
7052 else if(ColourNumber == 8)
7054 else if(ColourNumber == 9)
7056 else if(ColourNumber == 10)
7058 else if(ColourNumber == 11)
7060 else if(ColourNumber == 12)
7062 else if(ColourNumber == 13)
7064 else if(ColourNumber == 14)
7074 for(
int x = 0; x < 4; x++)
7081 for(
int x = 0; x < 4; x++)
7146 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
7149 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
7150 bool GiveMessagesFalse =
false;
7151 bool CheckLocationsExistInRailwayTrue =
true;
7157 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
7160 if(Marker[6] ==
'1')
7457 bool HideFlashingTrain =
true;
7460 Graphics::TBitmap *SmallTrainBitmap;
7501 HideFlashingTrain =
false;
7506 HideFlashingTrain =
false;
7511 HideFlashingTrain =
false;
7516 HideFlashingTrain =
false;
7521 HideFlashingTrain =
false;
7526 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
7530 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
7554 for(
int y = 0; y < 3; y++)
7558 bool FoundFlag =
false;
7569 if(IMPair.first != IMPair.second)
7596 if((LocationName ==
"") && (
MidElement > -1))
7600 if((LocationName ==
"") && (
LagElement > -1))
7604 if(LocationName ==
"")
7606 throw Exception(
"Error - Location name not set in TrainAtLocation");
7617 for(
int x = 0; x < 4; x++)
7629 for(
int x = 0; x < 4; x++)
7646 AnsiString(LinkNumber) +
"," +
HeadCode);
7697 int DistanceToRedSignal = 0;
7698 float TimeToAct = 0;
7699 float MinsEarly = 0;
7700 TDateTime DepartureTime;
7743 float CurrentStopTime;
7744 float LaterStopTime;
7745 float RecoverableTime;
7750 if(DistanceToRedSignal == -1)
7769 float TimeToSubtract, TotalStopTime;
7771 TimeToSubtract = RecoverableTime;
7797 if(CurrentStopTime > 0)
7798 TotalStopTime = CurrentStopTime + LaterStopTime;
7804 else if((MinsEarly > 0) && !
Stopped())
7806 TotalStopTime = LaterStopTime + MinsEarly;
7810 if(LaterStopTime == 0)
7811 TotalStopTime = CurrentStopTime;
7815 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
7818 if(AvTrackSpeed < 30)
7820 int Speed = AvTrackSpeed;
7828 TimeToAct = TotalStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
7848 if((NextEntryPos == 0) || (NextEntryPos == 2))
7960 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8001 int IncrementalMinutes = 0;
8002 int IncrementalDigits = 0;
8010 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
8036 if(AVEntry0.
Command ==
"Snt-sh")
8041 int IncrementalMinutes = 0;
8042 int IncrementalDigits = 0;
8050 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
8083 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8143 AnsiString Loc =
"";
8144 bool ElementFound =
false;
8149 ElementFound =
true;
8154 ElementFound =
true;
8159 ElementFound =
true;
8189 else if(AVEntryPtr->
Command ==
"Fer")
8191 bool CorrectExit =
false;
8299 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8314 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8329 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8340 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
8341 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
8342 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
8344 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
8345 "," + AnsiString(Mass) +
"," + ModeStr);
8347 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr +
"," + HeadCode);
8349 int RearExitPos = -1;
8351 for(
int x = 0; x < 4; x++)
8358 if(RearExitPos == -1)
8360 throw Exception(
"Error, RearExit == -1 in AddTrain");
8363 bool ReportFlag =
true;
8379 if(ModeStr ==
"Timetable")
8383 if(MaxRunningSpeed < 10)
8385 MaxRunningSpeed = 10;
8387 if(SignallerSpeed < 10)
8388 SignallerSpeed = 10;
8389 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
8390 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
8395 if(SignallerControl)
8426 if(!SignallerControl)
8441 if(!SignallerControl)
8452 AnsiString Loc =
"";
8469 if(!SignallerControl)
8490 int RouteNumber = -1;
8491 bool SignalsSet =
false;
8497 int RouteStartPosition;
8501 if(FirstPair.first == RouteNumber)
8503 RouteStartPosition = FirstPair.second;
8505 else if(SecondPair.first == RouteNumber)
8507 RouteStartPosition = SecondPair.second;
8511 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
8517 else if(RouteNumber > -1)
8537 int LinkedRouteNumber = -1;
8556 int RouteStartPosition;
8560 if(FirstPair.first == RouteNumber)
8562 RouteStartPosition = FirstPair.second;
8564 else if(SecondPair.first == RouteNumber)
8566 RouteStartPosition = SecondPair.second;
8570 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
8576 else if(RouteNumber > -1)
8596 int LinkedRouteNumber = -1;
8618 AnsiString(TrackVectorNumber));
8621 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8630 throw Exception(
"Error, VecPos not set in EntryPos");
8632 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
8637 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
8642 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
8656 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8664 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
8674 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8704 AnsiString RetStr =
"", PartStr =
"";
8712 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
8718 if(Ptr->SignallerControl)
8720 RetStr =
"Train under signaller control";
8725 if(Ptr->ArrivalTime == Ptr->DepartureTime)
8736 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
8740 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
8744 else if(Ptr->FormatType ==
PassTime)
8748 else if(Ptr->Command ==
"Fns")
8754 else if(Ptr->Command ==
"F-nshs")
8757 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
8764 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
8771 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
8774 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
8777 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
8784 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
8786 PartStr =
"Terminate at " + Ptr->LocationName;
8788 else if(Ptr->Command ==
"Frh")
8790 PartStr =
"Terminate at " + Ptr->LocationName;
8792 else if(Ptr->Command ==
"Fer")
8797 else if(Ptr->Command ==
"Fjo")
8800 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
8802 else if(Ptr->Command ==
"jbo")
8805 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
8807 else if(Ptr->Command ==
"fsp")
8812 else if(Ptr->Command ==
"rsp")
8817 else if(Ptr->Command ==
"cdt")
8822 RetStr = RetStr +
'\n' + PartStr;
8827 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
8840 + AnsiString(RptNum) +
",ControllerCheckNewServiceDepartureTime," + TDEPtr->
HeadCode);
8841 AnsiString DepTime =
"", EventTime =
"";
8842 bool CDTFlag =
false;
8846 if(AVI->Command ==
"cdt")
8851 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
8854 RetStr +=
"\nNew service splits at " + EventTime;
8858 if(AVI->Command ==
"jbo")
8861 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
8865 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
8870 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
8874 RetStr +=
"\nNew service departs at " + DepTime;
9032 ActiveTrackElementNameMapEntry.first =
Track->
TrackVector.at(x).ActiveTrackElementName;
9033 ActiveTrackElementNameMapEntry.second = 0;
9039 std::ifstream TTBLFile(FileName, std::ios_base::binary);
9042 if(TTBLFile.is_open())
9044 char *TrainTimetableString =
new char[10000];
9046 bool EndOfFile =
false;
9049 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9051 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9057 delete TrainTimetableString;
9061 AnsiString OneLine(TrainTimetableString);
9062 bool FinalCallFalse =
false;
9063 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9067 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9068 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9072 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
9074 delete TrainTimetableString;
9078 OneLine = AnsiString(TrainTimetableString);
9084 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9086 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9094 OneLine = AnsiString(TrainTimetableString);
9095 if(OneLine.Length() > 9999)
9097 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
9099 delete TrainTimetableString;
9103 bool FinalCallFalse =
false;
9104 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9108 delete TrainTimetableString;
9112 if(EndOfFile && (Count < 2))
9115 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
9117 delete TrainTimetableString;
9123 delete TrainTimetableString;
9128 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's not open in another application");
9139 bool CheckLocationsExistInRailway)
9264 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
9274 if(OneLine[1] !=
'*')
9276 int SCPos = OneLine.Pos(
';');
9283 bool AllCommas =
true;
9285 for(
int x = 1; x < OneLine.Length() + 1; x++)
9287 if(OneLine[x] !=
',')
9290 if(AllCommas || (OneLine ==
""))
9305 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
9306 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
9307 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
9308 TDateTime StartTime(0);
9310 bool Warning =
false;
9337 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
9338 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
9339 double MaxBrakeRate = 0;
9340 double PowerAtRail = 0;
9341 int SignallerSpeed = 0;
9342 if(OneLine[1] ==
'*')
9348 int Pos = OneLine.Pos(
',');
9351 int SubStringLength = 20;
9352 if(OneLine.Length() < 20)
9353 SubStringLength = OneLine.Length();
9354 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
9358 TrainInfoStr = OneLine.SubString(1, Pos - 1);
9359 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
9369 TempTrainDataEntry.
HeadCode = HeadCode;
9373 TempTrainDataEntry.
Mass = Mass;
9381 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
9384 while(NewRemainder[NewRemainder.Length()] ==
',')
9386 if(NewRemainder.Length() > 1)
9388 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
9397 if(NewRemainder ==
"")
9399 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
9405 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
9407 if(NewRemainder[x] ==
',')
9412 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
9414 int SubStringLength = 20;
9415 if(OneLine.Length() < 20)
9416 SubStringLength = OneLine.Length();
9418 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
9419 OneLine.SubString(1, SubStringLength) +
"'....");
9424 AnsiString OneEntry =
"";
9429 bool FinishFlag =
false;
9430 for(
int x = 0; x < CommaCount + 1; x++)
9432 if((CommaCount == 0) || (x < CommaCount))
9439 OneEntry = NewRemainder;
9444 Pos = NewRemainder.Pos(
',');
9445 OneEntry = NewRemainder.SubString(1, Pos - 1);
9446 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
9452 RearStartOrRepeatMins = 0;
9453 FrontStartOrRepeatDigits = 0;
9454 NumberOfRepeats = 0;
9455 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
9456 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
9458 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
9463 if(Warning && (Second ==
"Frh"))
9465 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
9469 if(Warning && (Second ==
"Fjo"))
9472 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
9478 if(SequenceType !=
Start)
9480 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
9484 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
9486 if(NewRemainder[1] !=
'R')
9489 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
9495 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
9499 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
9502 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
9508 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
9513 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
9518 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
9521 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
9528 if(SequenceType ==
Finish)
9543 ActionVectorEntry.
Warning = Warning;
9556 ActionVectorEntry.
Command = Second;
9569 else if(FormatType ==
TimeCmd)
9574 ActionVectorEntry.
Command = Second;
9581 ActionVectorEntry.
Command = Second;
9582 ActionVectorEntry.
ExitList = ExitList;
9589 ActionVectorEntry.
Command = Second;
9600 ActionVectorEntry.
Command = Second;
9610 ActionVectorEntry.
Command = Second;
9619 ActionVectorEntry.
Command = Second;
9627 ActionVectorEntry.
Command = Second;
9635 ActionVectorEntry.
Command = Second;
9641 ActionVectorEntry.
Command = Second;
9643 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
9648 OneEntry = NewRemainder;
9653 RearStartOrRepeatMins = 0;
9654 FrontStartOrRepeatDigits = 0;
9655 NumberOfRepeats = 0;
9656 if((FinishFlag) && (OneEntry[1] !=
'R'))
9659 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
9663 if(OneEntry[1] !=
'R')
9665 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
9666 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
9668 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
9672 if(SequenceType !=
Finish)
9674 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
9687 ActionVectorEntry.
Warning = Warning;
9693 ActionVectorEntry.
Command = Second;
9700 ActionVectorEntry.
Command = Second;
9708 ActionVectorEntry.
Command = Second;
9716 ActionVectorEntry.
Command = Second;
9725 ActionVectorEntry.
Command = Second;
9726 ActionVectorEntry.
ExitList = ExitList;
9730 ActionVectorEntry.
Command = Second;
9732 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
9737 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
9753 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
9772 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
9777 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
9792 if(TimeStr.Length() < 5)
9797 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
9802 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
9807 if(TimeStr[3] !=
':')
9812 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
9817 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
9822 while(TimeStr.Length() > 5)
9823 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
9824 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
9825 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
9827 if((WholeHours + FracHour) >= 95.98334)
9832 Time = TDateTime((WholeHours + FracHour) / 24);
9839 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
9840 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
9851 if(OneEntry.Length() > 0)
9853 if(OneEntry[1] ==
'W')
9856 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
9860 if(OneEntry ==
"Frh")
9870 if(OneEntry.Length() < 7)
9875 int Pos = OneEntry.Pos(
';');
9883 First = OneEntry.SubString(1, 5);
9889 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
9891 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
9894 if(Remainder.Length() < 7)
9899 Pos = Remainder.Pos(
';');
9906 Second = Remainder.SubString(1, 5);
9912 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
9925 Pos = Remainder.Pos(
';');
9954 if((Pos != 4) && (Pos != 7) && (Pos != 8))
9960 Second = Remainder.SubString(1, Pos - 1);
9962 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
9964 Pos = Remainder.Pos(
';');
9969 Third = Remainder.SubString(1, Pos - 1);
9970 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
9972 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
9975 int SpacePos = Third.Pos(
' ');
9981 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
9982 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
9984 if(CheckLocationsExistInRailway)
9997 SequenceType =
Start;
10006 SequenceType =
Start;
10018 if(Second ==
"Sns-sh")
10022 SequenceType =
Start;
10038 if(Second ==
"F-nshs")
10053 if(Second ==
"Sns-fsh")
10057 SequenceType =
Start;
10068 if(Second ==
"Fns-sh")
10089 if(Second ==
"pas")
10105 if(Second ==
"Fer")
10112 if(CheckLocationsExistInRailway)
10125 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
10126 (Second !=
"Frh-sh"))
10139 if(Second ==
"Frh-sh")
10143 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
10147 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
10151 if((Second ==
"Sfs") || (Second ==
"Sns"))
10153 SequenceType =
Start;
10171 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
10176 for(
int x = 1; x < LocStr.Length() + 1; x++)
10178 if(LocStr[x] <
' ')
10183 if(LocStr[x] >
'z')
10190 if(CheckLocationsExistInRailway)
10195 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
10196 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
10197 "that includes a continuation will not be valid.");
10215 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
10218 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Snt-sh, Sns-sh, Fns-sh or Frh-sh");
10223 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
10225 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
10227 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
10233 for(
int x = 3; x >= 0; x--)
10235 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
10236 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
10238 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
10254 AnsiString CurrentID =
"";
10256 if(IDSet.Length() == 0)
10258 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
10262 for(
int x = 1; x <= IDSet.Length(); x++)
10265 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
10267 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
10272 int Pos = IDSet.Pos(
' ');
10283 CurrentID = IDSet.SubString(1, Pos - 1);
10284 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
10296 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
10303 if(!ExitList.empty())
10307 if(*ELIT == VecPos)
10309 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
10316 ExitList.push_back(VecPos);
10326 Pos = IDSet.Pos(
' ');
10333 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
10340 AnsiString Remainder =
"";
10341 int SemiColonCount = 0;
10343 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
10345 if(TrainInfoStr[x] ==
';')
10348 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
10350 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
10351 "'. Should be headcode + optional description for a continuing service;" +
10352 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
10356 if(SemiColonCount == 0)
10358 HeadCode = TrainInfoStr;
10367 if(SemiColonCount == 1)
10369 Pos = TrainInfoStr.Pos(
';');
10370 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
10371 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
10377 if(Description ==
"")
10379 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
10383 if(Description.Length() > 60)
10385 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
10389 for(
int x = 1; x < Description.Length() + 1; x++)
10391 if((Description[x] <
' ') || (Description[x] >
'~'))
10393 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
10402 Pos = TrainInfoStr.Pos(
';');
10403 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
10404 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
10410 Pos = Remainder.Pos(
';');
10411 Description = Remainder.SubString(1, Pos - 1);
10412 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10413 if(Description ==
"")
10415 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
10419 if(Description.Length() > 60)
10421 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
10425 for(
int x = 1; x < Description.Length() + 1; x++)
10427 if((Description[x] <
' ') || (Description[x] > 126))
10429 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
10434 Pos = Remainder.Pos(
';');
10435 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
10437 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10438 if(StartSpeedStr ==
"")
10440 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
10444 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
10446 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
10448 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
10453 StartSpeed = StartSpeedStr.ToInt();
10459 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
10463 Pos = Remainder.Pos(
';');
10464 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
10466 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10467 if(MaxRunningSpeedStr ==
"")
10469 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
10473 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
10475 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
10477 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
10482 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
10488 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
10492 if(MaxRunningSpeed < 10)
10495 MaxRunningSpeed = 10;
10498 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
10502 Pos = Remainder.Pos(
';');
10503 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
10505 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10508 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
10512 for(
int x = 1; x < MassStr.Length() + 1; x++)
10514 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
10516 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
10521 Mass = MassStr.ToInt() * 1000;
10527 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
10533 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
10537 Pos = Remainder.Pos(
';');
10538 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
10540 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10541 if(MaxBrakeForceStr ==
"")
10543 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
10547 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
10549 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
10551 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
10556 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
10559 if((MaxBrakeForce / Mass) > 1)
10561 MaxBrakeForce = Mass;
10564 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
10568 if((MaxBrakeForce / Mass) < 0.01)
10570 MaxBrakeForce = Mass * 0.01;
10573 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
10578 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
10580 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
10582 if(SemiColonCount == 6)
10584 GrossPowerStr = Remainder;
10585 SignallerSpeedStr =
"30";
10589 Pos = Remainder.Pos(
';');
10590 GrossPowerStr = Remainder.SubString(1, Pos - 1);
10591 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10594 if(GrossPowerStr ==
"")
10596 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
10600 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
10602 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
10604 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
10610 double GrossPower = GrossPowerStr.ToInt() * 1000;
10617 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
10621 else if(GrossPower == 0)
10626 else if((GrossPower > 0) && (GrossPower < 10000))
10629 GrossPower = 10000;
10631 PowerAtRail = GrossPower * 0.8;
10635 if(SignallerSpeedStr ==
"")
10637 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
10641 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
10643 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
10645 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
10650 SignallerSpeed = SignallerSpeedStr.ToInt();
10656 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
10660 if(SignallerSpeed < 10)
10663 SignallerSpeed = 10;
10666 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
10684 if(OneEntry.Length() < 7)
10686 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
10690 int SemiColonCount = 0;
10692 for(
int x = 1; x < OneEntry.Length() + 1; x++)
10694 if(OneEntry[x] ==
';')
10697 if(SemiColonCount != 3)
10699 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
10703 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
10705 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
10709 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
10714 Pos = Remainder.Pos(
';');
10715 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
10717 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10718 if(MinutesStr ==
"")
10720 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
10724 if(MinutesStr.Length() > 3)
10727 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
10731 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
10733 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
10735 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
10740 RearStartOrRepeatMins = MinutesStr.ToInt();
10741 if(RearStartOrRepeatMins == 0)
10743 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
10747 Pos = Remainder.Pos(
';');
10748 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
10750 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10751 if(DigitsStr ==
"")
10753 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
10757 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
10759 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
10761 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
10766 if(DigitsStr.Length() > 2)
10768 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
10772 FrontStartOrRepeatDigits = DigitsStr.ToInt();
10786 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
10790 AnsiString NumberStr = Remainder;
10792 if(NumberStr ==
"")
10794 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
10798 if(NumberStr.Length() > 4)
10801 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
10805 for(
int x = 1; x < NumberStr.Length() + 1; x++)
10807 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
10810 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
10815 NumberOfRepeats = NumberStr.ToInt();
10816 if(NumberOfRepeats == 0)
10818 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
10974 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
10998 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
11012 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
11028 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
11040 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
11067 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
11078 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11083 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
11093 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11098 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
11108 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11119 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
11129 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
11141 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11148 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
11157 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
11177 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
11179 AnsiString LocationName =
"";
11195 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
11196 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
11205 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
11214 if(AVEntry0.
Command ==
"Snt-sh")
11228 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
11244 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
11245 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
11256 bool FoundFlag =
false;
11262 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11274 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
11287 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11296 ": an event should have had a location name associated with it but it could not be found");
11302 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
11322 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11332 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
11339 if(AVEntry.
Command ==
"F-nshs")
11344 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
11372 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
11373 ". The event isn't valid for a stationary train.");
11383 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
11391 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
11392 ". The event isn't valid for a stationary train.");
11410 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
11411 ". The event isn't valid for a stationary train.");
11421 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
11429 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
11430 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
11448 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
11449 ". The event isn't valid for a moving train.");
11471 bool LastEntryIsAnArrival =
false;
11478 LastEntryIsAnArrival =
false;
11479 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11486 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
11488 if(LastEntryIsAnArrival)
11492 LastEntryIsAnArrival =
false;
11498 LastEntryIsAnArrival =
true;
11505 LastEntryIsAnArrival =
true;
11506 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11513 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
11515 if(LastEntryIsAnArrival)
11519 LastEntryIsAnArrival =
false;
11525 LastEntryIsAnArrival =
true;
11535 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11543 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
11551 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
11552 ". The event isn't valid for a stationary train.");
11563 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
11571 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
11572 ". The event isn't valid for a moving train.");
11586 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11593 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
11597 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
11604 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
11608 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
11617 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
11621 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
11628 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
11639 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11650 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
11658 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
11673 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
11685 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
11697 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
11698 ", may be before timetable start time");
11709 AnsiString LastLocationName =
"";
11713 bool LastEntryIsAnArrival =
false;
11718 LastEntryIsAnArrival =
false;
11719 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
11720 if(LastLocationName !=
"")
11722 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
11724 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
11735 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11747 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11759 ShowMessage(
"Two or more locations are the same without a change of direction between them. Please correct if this is an error.\n\nThis warning will not be shown again.");
11768 LastEntryIsAnArrival =
false;
11772 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
11775 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
11780 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
11783 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
11789 LastEntryIsAnArrival = !LastEntryIsAnArrival;
11795 LastEntryIsAnArrival =
true;
11796 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
11797 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11807 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11819 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
11831 ShowMessage(
"Two or more locations are the same without a change of direction between them. Please correct if this is an error.\n\nThis warning will not be shown again.");
11840 LastEntryIsAnArrival =
false;
11844 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
11847 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
11855 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
11862 LastEntryIsAnArrival = !LastEntryIsAnArrival;
11870 AnsiString LocationNameToBeChecked =
"";
11875 unsigned int y = 0;
11890 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
11891 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
11907 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
11915 ShowMessage(
"Two or more locations are the same without a change of direction between them. Please correct if this is an error.\n\nThis warning will not be shown again.");
11934 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11939 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
11941 AnsiString LocName =
"";
11947 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
11954 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
11977 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12002 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12024 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12046 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12065 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12068 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
12083 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12088 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
12092 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
12096 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
12100 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
12137 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12139 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
12145 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
12158 int IncMinutes = 0;
12166 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12172 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
12178 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
12183 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
12189 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
12194 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
12207 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12233 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
12241 if(HeadCode.Length() > 4)
12243 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
12254 int ForwardCount = 0;
12255 int ReverseCount = 0;
12257 if(MainHeadCode == SecondHeadCode)
12259 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
12269 if(TDEntry.
HeadCode == MainHeadCode)
12271 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12286 if(ForwardCount == 0)
12289 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
12292 if(ForwardCount > 2)
12295 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
12296 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
12306 if(TDEntry.
HeadCode == SecondHeadCode)
12308 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12323 if(ReverseCount == 0)
12325 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
12330 if(ReverseCount > 2)
12333 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
12334 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
12340 if(ForwardCount != ReverseCount)
12342 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
12343 " than the other way round");
12375 int ForwardCount = 0;
12376 int ReverseCount = 0;
12377 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
12386 if(TDEntry.
HeadCode == MainHeadCode)
12388 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12391 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
12396 ForwardEntryPtr = &AVEntry;
12398 ForwardTDVectorNumber = x;
12401 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
12402 (AVEntry.
Command ==
"Frh-sh")))
12407 ForwardEntryPtr = &AVEntry;
12409 ForwardTDVectorNumber = x;
12415 if(ForwardCount == 0)
12418 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
12420 if(ForwardCount > 1)
12422 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
12433 if(TDEntry.
HeadCode == OtherHeadCode)
12435 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12438 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
12444 ReverseEntryPtr = &AVEntry;
12445 ReverseTDVectorNumber = x;
12448 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
12454 ReverseEntryPtr = &AVEntry;
12455 ReverseTDVectorNumber = x;
12462 if(ReverseCount == 0)
12464 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
12469 if(ReverseCount > 1)
12471 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
12479 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
12480 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
12481 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
12482 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
12486 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
12494 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
12500 if(ForwardEntryPtr->LocationName ==
"")
12502 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
12503 ". One or other service does not have a location set");
12511 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
12512 ". One or other service does not have a location set");
12518 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
12520 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
12521 " is at a different location to the referencing train " + MainHeadCode);
12530 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
12532 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
12533 " has a different event time to the referencing train " + MainHeadCode);
12542 if(ForwardShuttleStart && ReverseShuttleFinish)
12547 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
12548 " first repeat restart time not consistent with finish service " + OtherHeadCode);
12555 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
12558 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
12560 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
12561 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
12568 if(ReverseEntryPtr->
Command ==
"Fjo")
12571 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
12573 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
12574 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
12581 if(ReverseEntryPtr->
Command ==
"Fns")
12584 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
12586 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
12587 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
12594 if(ForwardEntryPtr->Command ==
"Sfs")
12596 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
12599 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
12607 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
12609 if(ReverseEntryPtr->
Command !=
"Sfs")
12611 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
12621 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
12628 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
12635 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
12640 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12650 if(ForwardEntryPtr->Command ==
"Sns")
12652 if(ReverseEntryPtr->
Command !=
"Fns")
12654 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
12655 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
12662 if(ForwardEntryPtr->Command ==
"Fns")
12664 if(ReverseEntryPtr->
Command !=
"Sns")
12666 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
12667 " and forms a new service with headcode " + OtherHeadCode);
12674 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12683 if(ForwardEntryPtr->Command ==
"jbo")
12685 if(ReverseEntryPtr->
Command !=
"Fjo")
12687 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
12688 " and is joined by a train with headcode " + OtherHeadCode);
12695 if(ForwardEntryPtr->Command ==
"Fjo")
12697 if(ReverseEntryPtr->
Command !=
"jbo")
12699 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
12700 " and joins a train with headcode " + OtherHeadCode);
12707 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12716 if(ForwardShuttleStart)
12719 if(!ReverseShuttleFinish)
12722 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
12723 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
12730 if(ReverseShuttleStart)
12733 if(!ForwardShuttleFinish)
12736 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
12737 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
12744 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
12757 bool MainRepeat =
false, OtherRepeat =
false;
12767 OtherRepeat =
true;
12770 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
12772 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
12773 " and the associated train with headcode " + OtherHeadCode);
12778 if(MainRepeat && OtherRepeat)
12784 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
12785 " and the associated train with headcode " + OtherHeadCode);
12807 while(Input[1] ==
' ')
12809 if(Input.Length() > 1)
12811 Input = Input.SubString(2, Input.Length() - 1);
12825 while(Input[Input.Length()] ==
' ')
12827 if(Input.Length() > 1)
12829 Input = Input.SubString(1, Input.Length() - 1);
12839 AnsiString Output =
"";
12840 bool DelimiterFound =
false;
12842 for(
int x = 1; x < Input.Length() + 1; x++)
12846 if(Input[x] ==
' ')
12849 if((Input[x] !=
',') && (Input[x] !=
';'))
12851 DelimiterFound =
false;
12852 Output = Output + Input[x];
12856 DelimiterFound =
true;
12857 Output = Output + Input[x];
12869 DelimiterFound =
false;
12870 for(
int x = Input.Length(); x > 0; x--)
12874 if(Input[x] ==
' ')
12877 if((Input[x] !=
',') && (Input[x] !=
';'))
12879 DelimiterFound =
false;
12880 Output = AnsiString(Input[x]) + Output;
12884 DelimiterFound =
true;
12885 Output = AnsiString(Input[x]) + Output;
12905 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
12907 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
12918 LocationName = LocRear;
12920 LocationName = LocFront;
12921 if(LocationName ==
"")
12947 AnsiString TimeLocLocationName;
12948 bool FoundFlag =
false;
12950 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
12965 if(TimeLocLocationName == LocationName)
12982 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
12985 if(RearPosition < 0)
12992 if(FrontPosition < 0)
13003 for(
int x = 0; x < 4; x++)
13005 if(RearTrackElement.
Conn[x] == FrontPosition)
13020 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
13028 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
13034 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
13040 if((RearType ==
Points) && (RearExitPos == 3))
13042 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
13049 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
13064 AnsiString(RearExitPos));
13071 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
13073 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
13076 AnsiString RearName, FrontName;
13085 FrontName = FrontTrackElement.
ElementID;
13088 int LockedVectorNumber;
13223 "," + AnsiString(IncDigits));
13226 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
13231 return BaseHeadCode;
13233 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
13234 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
13236 while(NextRepeatDigits >= 100)
13238 NextRepeatDigits -= 100;
13240 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
13242 if(NextRepeatDigitsStr.Length() < 2)
13243 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
13244 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
13247 return NextRepeatHeadCode;
13255 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
13256 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
13259 return NextRepeatTime;
13268 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
13269 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
13270 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
13271 int RepeatSecs = RepeatMinutes * 60;
13273 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
13291 NonRepeatingHeadCode);
13292 int ForwardCount = 0;
13293 int ReverseCount = 0;
13294 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
13304 if(TDEntry.
HeadCode == MainHeadCode)
13306 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13312 ForwardEntryPtr = &AVEntry;
13314 ForwardTDVectorNumber = x;
13319 if(ForwardCount == 0)
13322 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
13324 if(ForwardCount > 1)
13326 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
13337 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
13339 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13346 ReverseEntryPtr = &AVEntry;
13347 ReverseTDVectorNumber = x;
13353 if(ReverseCount == 0)
13355 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
13360 if(ReverseCount > 1)
13362 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
13363 NonRepeatingHeadCode);
13369 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
13371 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
13377 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
13379 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
13385 if(ForwardEntryPtr->LocationName ==
"")
13387 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
13388 ". One or other service does not have a location set");
13396 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
13397 ". One or other service does not have a location set");
13403 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
13405 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
13406 " is at a different location to the referencing train " + MainHeadCode);
13412 if(ForwardEntryPtr->Command ==
"F-nshs")
13415 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
13417 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
13418 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
13425 if(ForwardEntryPtr->Command ==
"Fns-sh")
13429 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
13431 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
13432 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
13439 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
13442 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13444 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
13445 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
13463 if(ForwardEntryPtr->Command ==
"Sns-sh")
13465 if(ReverseEntryPtr->
Command !=
"F-nshs")
13467 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
13468 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
13475 if(ForwardEntryPtr->Command ==
"F-nshs")
13477 if(ReverseEntryPtr->
Command !=
"Sns-sh")
13479 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
13480 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
13487 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13497 if(ForwardEntryPtr->Command ==
"Sns-fsh")
13499 if(ReverseEntryPtr->
Command !=
"Fns-sh")
13502 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
13503 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
13510 if(ForwardEntryPtr->Command ==
"Fns-sh")
13512 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
13515 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
13516 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
13523 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
13546 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
13547 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
13548 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
13549 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
13551 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
13575 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
13578 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
13579 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
13581 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
13583 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
13588 while(LastActionCommand ==
"Fns")
13590 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
13591 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
13592 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
13595 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
13596 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
13603 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
13606 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
13607 ". The linking of two or more shuttles is not permitted.");
13625 ShowMessage(Message);
13639 ShowMessage(Message);
13677 AnsiString(ActionEventType) +
"," + LocationID);
13678 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
13680 Prefix =
" ERROR: ";
13683 Prefix =
" HELD: ";
13684 ErrorLog =
" can't enter railway, train obstructing entry position ";
13685 WarningStr =
" can't enter railway, train obstructing entry position ";
13690 Prefix =
" HELD: ";
13691 ErrorLog =
" can't be created, train obstructing ";
13692 WarningStr =
" can't be created, train obstructing ";
13697 Prefix =
" HELD: ";
13698 ErrorLog =
" can't be created on a locked route at ";
13699 WarningStr =
" can't be created on a locked route at ";
13704 Prefix =
" HELD: ";
13705 ErrorLog =
" can't enter on a locked route at ";
13706 WarningStr =
" can't enter on a locked route at ";
13711 Prefix =
" HELD: ";
13712 ErrorLog =
" can't be created, diverging points at ";
13713 WarningStr =
" can't be created, diverging points at ";
13718 ErrorLog =
" left railway unexpectedly at ";
13723 ErrorLog =
" left railway at an incorrect exit at ";
13728 ErrorLog =
" failed to split - location too short at ";
13729 WarningStr =
" failed to split, location too short at ";
13734 Prefix =
" HELD: ";
13735 ErrorLog =
" unable to split - other train obstructing at ";
13736 WarningStr =
" unable to split - other train obstructing at ";
13740 ErrorLog =
" stopped at buffers unexpectedly at position ";
13743 ErrorLog =
" failed to stop at ";
13748 ErrorLog =
" failed to split at ";
13753 ErrorLog =
" failed to be joined by other train at ";
13758 ErrorLog =
" failed to join other train at ";
13763 ErrorLog =
" failed to terminate at ";
13768 ErrorLog =
" failed to form new service at ";
13773 ErrorLog =
" failed to exit railway ";
13778 ErrorLog =
" failed to change direction at ";
13783 ErrorLog =
" failed to pass ";
13787 ErrorLog =
" facing buffers and unable to start at ";
13790 ErrorLog =
" DERAILED at position ";
13791 Prefix =
" DERAILMENT: ";
13796 ErrorLog =
" CRASHED INTO BUFFERS at ";
13797 Prefix =
" CRASH: ";
13802 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
13803 Prefix =
" CRASH: ";
13808 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
13809 Prefix =
" CRASH: ";
13813 else if(ActionEventType ==
FailSPAD)
13815 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
13816 Prefix =
" SPAD: ";
13821 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
13822 Prefix =
" SPAD RISK: ";
13827 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
13831 Prefix =
" WARNING: ";
13832 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
13833 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
13838 Prefix =
" WARNING: ";
13839 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
13840 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
13879 std::ofstream OutFile(
"TrainData.csv");
13883 ShowMessage(
"Output file TrainData.csv failed to open");
13890 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
13895 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
13896 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
13897 "RepeatNumber" <<
'\n' <<
'\n';
13898 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13901 AnsiString TimetableEntryTypeStr;
13907 TimetableEntryTypeStr =
"NoFormat";
13913 TimetableEntryTypeStr =
"TimeLoc";
13919 TimetableEntryTypeStr =
"TimeTimeLoc";
13925 TimetableEntryTypeStr =
"TimeCmd";
13931 TimetableEntryTypeStr =
"StartNew";
13937 TimetableEntryTypeStr =
"TimeCmdHeadCode";
13943 TimetableEntryTypeStr =
"FinRemHere";
13949 TimetableEntryTypeStr =
"FNSShuttle";
13955 TimetableEntryTypeStr =
"SNTShuttle";
13961 TimetableEntryTypeStr =
"SNSShuttle";
13967 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
13973 TimetableEntryTypeStr =
"FSHNewService";
13979 TimetableEntryTypeStr =
"Repeat";
13985 TimetableEntryTypeStr =
"Default";
13995 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
13996 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
13999 AnsiString RunningEntryStr;
14005 RunningEntryStr =
"NotStarted";
14011 RunningEntryStr =
"Running";
14017 RunningEntryStr =
"Exited";
14020 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
14037 ShowMessage(Message);
14038 BaseTime = TDateTime::CurrentDateTime();
14052 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
14065 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
14068 for(
int x = 0; x < NumberOfTrains; x++)
14070 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
14090 int NumberOfTrains;
14097 for(
int x = 0; x < NumberOfTrains; x++)
14134 for(
int x = 0; x < LockedRouteVectorSize; x++)
14141 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
14152 int LockedRouteVectorSize;
14159 for(
int x = 0; x < LockedRouteVectorSize; x++)
14217 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
14225 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
14236 int ContinuationAutoSigVectorSize;
14243 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
14313 if(AVFirstEntry.
Command ==
"Snt")
14337 CTEMMP.second = CTEEntry;
14344 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
14352 CTEMMP.second = CTEEntry;
14373 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
14390 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
14392 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
14403 AnsiString RetStr =
"", PartStr =
"";
14518 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
14522 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
14524 AnsiString ShortTTName =
"";
14526 for(
int x = TTFileName.Length(); x > 0; x--)
14528 if(TTFileName[x] ==
'\\')
14530 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
14535 ShowMessage(
"Creates two timetables named " + ShortTTName +
14536 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
14538 Screen->Cursor = TCursor(-11);
14540 AnsiString FormatNoDPStr =
"#######0";
14541 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
14544 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
14551 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
14553 if(TrainDataEntry.
Mass > 0)
14554 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
14556 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
14558 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
14560 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
14561 FirstHeadCode = TrainDataEntry.
HeadCode;
14562 int IncDigits = 0, IncMinutes = 0;
14564 if(!ActionVector.empty())
14566 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
14568 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
14569 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
14578 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
14579 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
14584 for(
unsigned int z = 0; z < ActionVector.size(); z++)
14589 AnsiString PartStr =
"", TimeStr =
"";
14606 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
14610 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
14620 PartStr =
"Enters at " + LocName;
14633 PartStr =
"Created at " + LocName;
14647 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
14652 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
14657 else if(ActionVectorEntry.
Command ==
"Sfs")
14659 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
14663 else if(ActionVectorEntry.
Command ==
"Sns")
14665 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
14673 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
14679 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
14686 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
14689 AnsiString FirstHeadCode = TDE->
HeadCode;
14693 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
14705 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
14707 OneTTEntry.
Action = PartStr;
14708 OneTTEntry.
Time = TimeStr;
14710 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
14715 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
14721 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
14726 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
14734 else if(ActionVectorEntry.
Command ==
"jbo")
14736 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
14740 else if(ActionVectorEntry.
Command ==
"fsp")
14742 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
14746 else if(ActionVectorEntry.
Command ==
"rsp")
14748 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
14752 else if(ActionVectorEntry.
Command ==
"cdt")
14754 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
14760 if(ActionVectorEntry.
Command ==
"Fns")
14762 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14766 else if(ActionVectorEntry.
Command ==
"F-nshs")
14768 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14774 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
14781 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14787 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
14794 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
14799 else if(ActionVectorEntry.
Command ==
"Frh")
14801 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
14806 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
14810 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
14818 else if(ActionVectorEntry.
Command ==
"Fer")
14823 else if(ActionVectorEntry.
Command ==
"Fjo")
14825 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
14832 OneTTEntry.
Action = PartStr;
14833 OneTTEntry.
Time = TimeStr;
14840 AllTTTrains->push_back(OneTTLine);
14844 std::ofstream TTFile(TTFileName.c_str());
14848 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
14849 delete AllTTTrains;
14885 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
14886 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
14888 TTFile << AllTTTrains->at(x).Header.c_str();
14891 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
14893 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
14895 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
14899 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
14902 TTFile <<
'\n' <<
'\n';
14904 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
14906 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
14907 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
14909 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
14911 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
14915 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
14920 TTFile <<
'\n' <<
'\n';
14925 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
14927 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
14929 std::ofstream TTFile2(TTFileName2.c_str());
14933 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
14934 delete AllTTTrains;
14939 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
14940 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
14941 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
14943 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
14948 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
14949 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
14951 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
14953 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
14955 bool GiveMessagesFalse =
false;
14956 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
14957 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
14958 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
14962 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
14963 TimeString = TimeString.SubString(9, 5);
14964 ActionString +=
" " + OtherHeadCode;
14966 if(TimeString.SubString(1, 7) ==
"End at ")
14969 TimeString = TimeString.SubString(8, 5);
14971 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
14972 AnsiMultiMapEntry.first = TimeString;
14973 AnsiMultiMapEntry.second = OneLine;
14974 TAMM->insert(AnsiMultiMapEntry);
14979 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
14981 TTFile2 << (AMMIT->second).c_str();
14983 delete AllTTTrains;
14992 bool AtLocChecked,
int ArrRange,
int DepRange)
14996 bool AnalysisError =
false;
15020 TTrainDataVector::iterator TDVIt, TDVCopyIt;
15022 int IteratorNumber = 0;
15023 AnsiString AnsiSuffix =
"";
15028 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
15030 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
15033 AnsiSuffix = AnsiString(Suffix);
15034 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
15041 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
15042 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
15047 ServiceCallingLocsList.clear();
15048 if(ActionVector.empty())
15052 if(ActionVector.at(0).SignallerControl)
15056 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15074 int HLoc = TE.
HLoc;
15075 int VLoc = TE.
VLoc;
15076 AnsiString HString;
15077 AnsiString VString;
15080 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15084 HString = AnsiString(HLoc);
15088 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15092 VString = AnsiString(VLoc);
15094 ServiceCallingLocsList.push_back(HString +
'-' + VString);
15117 else if(AVE.
Command ==
"cdt")
15119 if(ActionVector.at(z-1).SequenceType ==
Start)
15123 else if(ActionVector.at(z+1).SequenceType ==
Finish)
15130 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
15139 ServiceCallingLocsList.push_back(LName);
15143 int HLoc = TE.
HLoc;
15144 int VLoc = TE.
VLoc;
15145 AnsiString HString;
15146 AnsiString VString;
15149 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15153 HString = AnsiString(HLoc);
15157 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15161 VString = AnsiString(VLoc);
15163 ServiceCallingLocsList.push_back(HString +
'-' + VString);
15167 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
15201 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
15207 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
15208 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
15209 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
15213 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
15218 TDateTime LastTDTime;
15219 int IncMinutes = 0;
15221 if(ActionVector.empty())
15225 if(ActionVector.at(0).SignallerControl)
15229 if(AVLast->FormatType ==
Repeat)
15231 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15239 if(AVLast->ArrivalTime != TDateTime(-1))
15241 LastTDTime = AVLast->ArrivalTime;
15243 else if(AVLast->EventTime != TDateTime(-1))
15245 LastTDTime = AVLast->EventTime;
15294 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
15299 int IncMinutes = 0;
15301 if(ActionVector.empty())
15305 if(ActionVector.at(0).SignallerControl)
15309 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
15311 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15314 for(
int y = 0; y < NumTrains; y++)
15328 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15343 LocServiceTimesVector.push_back(TLSTEntry);
15346 AnsiString IncTime =
"", FoundStopTime =
"";
15347 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
15349 if(ActionVector.at(a).FormatType ==
TimeLoc)
15354 if(ActionVector.at(a).SequenceType ==
Finish)
15360 if(FoundStopTime ==
"")
15362 throw Exception(
"Failure to determine FoundStopTime for located Snt");
15364 int WhileCount = 0;
15373 if(IncTime >= FoundStopTime)
15377 LocServiceTimesVector.push_back(TLSTEntry);
15378 if(WhileCount > 2000)
15380 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
15393 int HLoc = TE.
HLoc;
15394 int VLoc = TE.
VLoc;
15395 AnsiString HString;
15396 AnsiString VString;
15399 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15403 HString = AnsiString(HLoc);
15407 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15411 VString = AnsiString(VLoc);
15413 TLSTEntry.
Location = HString +
'-' + VString;
15417 LocServiceTimesVector.push_back(TLSTEntry);
15425 LocServiceTimesVector.push_back(TLSTEntry);
15427 AnsiString IncTime =
"", FoundStopTime =
"";
15428 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
15430 if(ActionVector.at(a).FormatType ==
TimeLoc)
15435 if(ActionVector.at(a).SequenceType ==
Finish)
15441 if(FoundStopTime ==
"")
15443 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
15445 int WhileCount = 0;
15454 if(IncTime >= FoundStopTime)
15458 LocServiceTimesVector.push_back(TLSTEntry);
15459 if(WhileCount > 2000)
15461 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
15471 bool SkipAddingMinutes =
false;
15474 LocServiceTimesVector.push_back(TLSTEntry);
15476 AnsiString IncTime =
"", FoundStopTime =
"";
15477 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
15479 if(ActionVector.at(a).FormatType ==
TimeLoc)
15484 if(ActionVector.at(a).SequenceType ==
Finish)
15487 if((a == z + 1) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
15490 LocServiceTimesVector.pop_back();
15491 SkipAddingMinutes =
true;
15496 if(FoundStopTime ==
"")
15498 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
15500 if(!SkipAddingMinutes)
15502 int WhileCount = 0;
15511 if(IncTime >= FoundStopTime)
15515 LocServiceTimesVector.push_back(TLSTEntry);
15516 if(WhileCount > 2000)
15518 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
15527 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
15529 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
15531 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
15532 LocServiceTimesVector.pop_back();
15533 LocServiceTimesVector.push_back(TLSTEntry);
15538 LocServiceTimesVector.push_back(TLSTEntry);
15544 LocServiceTimesVector.push_back(TLSTEntry);
15563 LocServiceTimesVector.push_back(TLSTEntry);
15567 AnsiString TempDepTime = TLSTEntry.
DepTime;
15569 LocServiceTimesVector.push_back(TLSTEntry);
15571 while(TLSTEntry.
AtLocTime < TempDepTime)
15576 TLSTEntry.
DepTime = TempDepTime;
15577 LocServiceTimesVector.push_back(TLSTEntry);
15581 LocServiceTimesVector.push_back(TLSTEntry);
15599 AnsiString HString;
15600 AnsiString VString;
15603 HString =
'N' + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15607 HString = AnsiString(HLoc);
15611 VString =
'N' + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15615 VString = AnsiString(VLoc);
15617 TLSTEntry.
Location = HString +
'-' + VString;
15619 LocServiceTimesVector.push_back(TLSTEntry);
15624 AnsiString FrhTime;
15625 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
15629 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
15637 LocServiceTimesVector.push_back(TLSTEntry);
15643 LocServiceTimesVector.push_back(TLSTEntry);
15648 else if(AVE.
Command ==
"Frh-sh")
15650 if(y == NumTrains - 1)
15656 LocServiceTimesVector.push_back(TLSTEntry);
15662 LocServiceTimesVector.push_back(TLSTEntry);
15681 TLocServiceTimesVector::iterator Ptr1, Ptr2;
15684 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15685 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
15687 std::ofstream TTFile3(TTFileName3.c_str());
15691 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
15696 if(LocServiceTimesVector.empty())
15698 ShowMessage(
"No timetabled services found");
15700 DeleteFile(TTFileName3);
15705 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n\n\n";
15712 Ptr1 = LocServiceTimesVector.begin();
15714 while(Ptr2 != LocServiceTimesVector.end())
15716 while(Ptr2->Location == Ptr1->Location)
15719 if(Ptr2 == LocServiceTimesVector.end())
15726 if(Ptr2 != LocServiceTimesVector.end())
15734 TTFile3 <<
"Arrival analysis: an asterisk means that the number of same approach code arrivals is equal to or greater than the number of platforms.\n";
15735 TTFile3 <<
"If the total number of arrivals exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
15736 MinuteString =
" minutes";
15737 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
15740 MinuteString =
" minute";
15742 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
15743 TTFile3 <<
",Platforms,Trains\n\n";
15745 Ptr1 = LocServiceTimesVector.begin();
15747 while(Ptr2 != LocServiceTimesVector.end())
15749 PreviousService =
"";
15750 NumTrainsAtLoc = 0;
15751 ServiceAndRepeatNumTotal =
"";
15753 NumPlatsAtThisLocCalculated =
false;
15755 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
15757 PreviousService =
"";
15758 NumTrainsAtLoc = 0;
15759 ServiceAndRepeatNumTotal =
"";
15761 NumPlatsAtThisLocCalculated =
false;
15765 if(Ptr2 == LocServiceTimesVector.end())
15770 if(Ptr2 == LocServiceTimesVector.end())
15774 while(Ptr2->Location == Ptr1->Location)
15776 PreviousService =
"";
15777 NumTrainsAtLoc = 0;
15778 ServiceAndRepeatNumTotal =
"";
15779 BasicTime = Ptr1->ArrTime;
15780 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
15784 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
15786 BasicTime = Ptr2->ArrTime;
15789 if(Ptr2 == LocServiceTimesVector.end())
15793 if(Ptr2->Location != Ptr1->Location)
15798 if(Ptr2 == LocServiceTimesVector.end())
15802 if(Ptr2->Location != Ptr1->Location)
15808 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
15812 if(!NumPlatsAtThisLocCalculated)
15815 NumPlatsAtThisLocCalculated =
true;
15817 if(Ptr1->ServiceAndRepeatNum != PreviousService)
15819 if(ServiceAndRepeatNumTotal ==
"")
15821 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
15822 NumTrainsAtLoc = 1;
15826 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
15829 PreviousService = Ptr2->ServiceAndRepeatNum;
15830 if(ServiceAndRepeatNumTotal ==
"")
15832 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
15833 NumTrainsAtLoc = 1;
15837 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
15841 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
15843 int MaxNumberOfSameDirections = 0;
15844 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
15849 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
15853 AnsiString Asterisk =
"";
15854 if(MaxNumberOfSameDirections >= NumPlats)
15859 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
15860 ArrivalsPrinted =
true;
15861 ServiceAndRepeatNumTotal =
"";
15863 if(Ptr2 == LocServiceTimesVector.end())
15867 if(Ptr2->Location != Ptr1->Location)
15872 if(Ptr2 == LocServiceTimesVector.end())
15878 if(!ArrivalsPrinted)
15880 TTFile3 <<
"Nothing to report for arrivals";
15882 TTFile3 <<
"\n\n\n";
15890 Ptr1 = LocServiceTimesVector.begin();
15892 while(Ptr2 != LocServiceTimesVector.end())
15894 while(Ptr2->Location == Ptr1->Location)
15897 if(Ptr2 == LocServiceTimesVector.end())
15904 if(Ptr2 != LocServiceTimesVector.end())
15911 TTFile3 <<
"Departure analysis: an asterisk means that the number of same exit code departures is equal to or greater than the number of platforms.\n";
15912 TTFile3 <<
"If the total number of departures exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
15913 MinuteString =
" minutes";
15914 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
15917 MinuteString =
" minute";
15919 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
15920 TTFile3 <<
",Platforms,Trains\n\n";
15922 Ptr1 = LocServiceTimesVector.begin();
15924 while(Ptr2 != LocServiceTimesVector.end())
15926 PreviousService =
"";
15927 NumTrainsAtLoc = 0;
15928 ServiceAndRepeatNumTotal =
"";
15930 NumPlatsAtThisLocCalculated =
false;
15932 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
15934 PreviousService =
"";
15935 NumTrainsAtLoc = 0;
15936 ServiceAndRepeatNumTotal =
"";
15938 NumPlatsAtThisLocCalculated =
false;
15942 if(Ptr2 == LocServiceTimesVector.end())
15947 if(Ptr2 == LocServiceTimesVector.end())
15951 while(Ptr2->Location == Ptr1->Location)
15953 PreviousService =
"";
15954 NumTrainsAtLoc = 0;
15955 ServiceAndRepeatNumTotal =
"";
15956 BasicTime = Ptr1->DepTime;
15957 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
15961 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
15963 BasicTime = Ptr2->DepTime;
15966 if(Ptr2 == LocServiceTimesVector.end())
15970 if(Ptr2->Location != Ptr1->Location)
15975 if(Ptr2 == LocServiceTimesVector.end())
15979 if(Ptr2->Location != Ptr1->Location)
15985 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
15989 if(!NumPlatsAtThisLocCalculated)
15992 NumPlatsAtThisLocCalculated =
true;
15994 if(Ptr1->ServiceAndRepeatNum != PreviousService)
15996 if(ServiceAndRepeatNumTotal ==
"")
15998 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
15999 NumTrainsAtLoc = 1;
16003 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
16006 PreviousService = Ptr2->ServiceAndRepeatNum;
16007 if(ServiceAndRepeatNumTotal ==
"")
16009 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
16010 NumTrainsAtLoc = 1;
16014 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
16018 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
16020 int MaxNumberOfSameDirections = 0;
16021 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
16026 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
16030 AnsiString Asterisk =
"";
16031 if(MaxNumberOfSameDirections >= NumPlats)
16036 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
16037 DeparturesPrinted =
true;
16038 ServiceAndRepeatNumTotal =
"";
16040 if(Ptr2 == LocServiceTimesVector.end())
16044 if(Ptr2->Location != Ptr1->Location)
16049 if(Ptr2 == LocServiceTimesVector.end())
16055 if(!DeparturesPrinted)
16057 TTFile3 <<
"Nothing to report for departures";
16059 TTFile3 <<
"\n\n\n";
16069 Ptr1 = LocServiceTimesVector.begin();
16071 while(Ptr2 != LocServiceTimesVector.end())
16073 while(Ptr2->Location == Ptr1->Location)
16076 if(Ptr2 == LocServiceTimesVector.end())
16083 if(Ptr2 != LocServiceTimesVector.end())
16090 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
16091 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
16092 TTFile3 <<
",Platforms,Trains,\n\n";
16093 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
16094 Ptr1 = LocServiceTimesVector.begin();
16096 while(Ptr2 != LocServiceTimesVector.end())
16098 PreviousService =
"";
16099 ServiceAndRepeatNumTotal =
"";
16100 NumTrainsAtLoc = 0;
16102 NumPlatsAtThisLocCalculated =
false;
16104 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
16106 PreviousService =
"";
16107 ServiceAndRepeatNumTotal =
"";
16108 NumTrainsAtLoc = 0;
16110 NumPlatsAtThisLocCalculated =
false;
16114 if(Ptr2 == LocServiceTimesVector.end())
16119 if(Ptr2 == LocServiceTimesVector.end())
16123 while(Ptr2->Location == Ptr1->Location)
16125 if(Ptr1->FrhMarker ==
"Frh")
16128 Ptr1->FrhMarker =
"FrhCounted";
16130 PreviousService =
"";
16131 NumTrainsAtLoc = 0;
16132 ServiceAndRepeatNumTotal =
"";
16133 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
16137 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
16140 if(Ptr1->FrhMarker ==
"Frh")
16143 Ptr1->FrhMarker =
"FrhCounted";
16146 if(Ptr2 == LocServiceTimesVector.end())
16150 if(Ptr2->Location != Ptr1->Location)
16155 if(Ptr2 == LocServiceTimesVector.end())
16159 if(Ptr2->Location != Ptr1->Location)
16163 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
16165 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
16169 if(!NumPlatsAtThisLocCalculated)
16172 NumPlatsAtThisLocCalculated =
true;
16174 if(Ptr1->ServiceAndRepeatNum != PreviousService)
16176 if(ServiceAndRepeatNumTotal ==
"")
16178 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
16179 NumTrainsAtLoc = 1;
16183 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
16186 PreviousService = Ptr2->ServiceAndRepeatNum;
16187 if(ServiceAndRepeatNumTotal ==
"")
16189 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
16190 NumTrainsAtLoc = 1;
16194 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
16197 if(Ptr1->FrhMarker ==
"Frh")
16200 Ptr1->FrhMarker =
"FrhCounted";
16203 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
16207 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
16209 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
16211 AnsiString Asterisk =
"";
16212 if(NumTrainsAtLoc > NumPlats)
16219 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
16221 else if(FrhCount == 1)
16223 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
16227 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
16229 LastFrhCount = FrhCount;
16230 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
16231 AtLocsPrinted =
true;
16232 ServiceAndRepeatNumTotal =
"";
16235 if(Ptr2 == LocServiceTimesVector.end())
16239 if(Ptr2->Location != Ptr1->Location)
16244 if(Ptr2 == LocServiceTimesVector.end())
16252 TTFile3 <<
"Nothing to report for trains at locations";
16254 TTFile3 <<
"\n\n\n";
16276 catch(
const Exception &e)
16278 AnsiString TTErrorFileName =
"Analysis Error.txt";
16279 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
16280 std::ofstream TTError(TTErrorFileName.c_str());
16283 ShowMessage(
"Analysis error file failed to open - can't be created");
16287 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16288 TTError << TimeNow.c_str() <<
"\n" << ArrRange <<
"\n" << ArrChecked <<
"\n" << DepRange <<
"\n" <<
16289 DepChecked <<
"\n" << AtLocChecked <<
"\n" << AnsiString(e.Message);
16291 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
16303 if((Time1 ==
"") || (Time2 ==
""))
16308 int Mins = Time1.SubString(4,2).ToInt();
16309 int Hours = Time1.SubString(1,2).ToInt();
16310 int Time1Mins = (Hours * 60) + Mins;
16311 Mins = Time2.SubString(4,2).ToInt();
16312 Hours = Time2.SubString(1,2).ToInt();
16313 int Time2Mins = (Hours * 60) + Mins;
16314 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
16326 bool &AnalysisError,
int &MaxNumberOfSameDirections)
16332 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
16334 std::list<AnsiString> ServiceList;
16336 bool EvenComma =
false;
16337 for(
int x = 1; x <= Input.Length(); x++)
16339 TempStr1 = Input[x];
16340 if(TempStr1 == AnsiString(
',') && EvenComma)
16346 TempStr2 += Input[x];
16348 if(TempStr1 == AnsiString(
','))
16350 EvenComma = !EvenComma;
16354 while(TempStr2.Length() > 0)
16356 SCPos = TempStr2.Pos(
';');
16359 OneService = TempStr2.SubString(1, SCPos - 1);
16360 ServiceList.push_back(OneService);
16361 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
16365 ServiceList.push_back(TempStr2);
16369 ServiceList.sort();
16370 ServiceList.unique();
16371 NumTrainsAtLoc = ServiceList.size();
16374 int DirectionMarker = 0;
16376 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
16378 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16380 *SLIt = *SLIt +
"&0";
16382 SLIt3 = ServiceList.end();
16384 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
16385 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
16386 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
16388 MaxNumberOfSameDirections = 0;
16389 int SameDirectionCount = 0;
16391 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
16395 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
16401 CommaPos1 = SLIt1->Pos(
',');
16402 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
16404 SpacePos = ServiceRef1.Pos(
' ');
16408 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
16409 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
16410 if(RepeatInfo1[1] ==
'F')
16416 SpacePos = RepeatInfo1.Pos(
' ');
16417 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
16420 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
16422 AmpersandPos = AnsiTime1.Pos(
'&');
16423 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
16428 throw Exception(
"ASCLIt1 Error in " + Input);
16430 ServiceCallingLocsList1 = ASCLIt1->second;
16431 AmpersandPos = SLIt1->Pos(
'&');
16432 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
16433 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
16435 SameDirectionCount = 1;
16436 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
16438 CommaPos2 = SLIt2->Pos(
',');
16439 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
16441 SpacePos = ServiceRef2.Pos(
' ');
16445 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
16446 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
16447 if(RepeatInfo2[1] ==
'F')
16453 SpacePos = RepeatInfo2.Pos(
' ');
16454 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
16458 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
16460 AmpersandPos = AnsiTime2.Pos(
'&');
16461 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
16466 throw Exception(
"ASCLIt2 Error in " + Input);
16468 ServiceCallingLocsList2 = ASCLIt2->second;
16470 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
16472 int AmpersandPos = SLIt2->Pos(
'&');
16473 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
16474 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
16475 SameDirectionCount++;
16478 if(SameDirectionCount > MaxNumberOfSameDirections)
16480 MaxNumberOfSameDirections = SameDirectionCount;
16485 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
16487 AmpersandPos = SLIt3->Pos(
'&');
16488 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
16489 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
16493 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16496 AmpersandPos = SLIt->Pos(
'&');
16497 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
16498 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
16499 DirectionMarker = DirectionMarkerString.ToInt();
16500 AnsiString DirectionSuffix =
"";
16502 if(DirectionMarker < 27)
16504 c = 64 + DirectionMarker;
16505 DirectionSuffix =
"," + AnsiString(c);
16507 else if(DirectionMarker < 53)
16509 c = 65 + DirectionMarker - 27;
16510 DirectionSuffix =
",A" + AnsiString(c);
16514 DirectionSuffix =
",?";
16516 *SLIt = ServiceWithoutMarker + DirectionSuffix;
16519 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16521 Output = Output + *SLIt +
",";
16523 if(Output.Length() > 0)
16525 Output = Output.SubString(1, Output.Length() - 1);
16531 catch(
const Exception &e)
16533 AnalysisError =
true;
16544 AnsiString InternalInput = Input, Output =
"", OneService =
"";
16546 std::list<AnsiString> ServiceList;
16548 while(InternalInput.Length() > 0)
16550 CommaPos = InternalInput.Pos(
',');
16553 OneService = InternalInput.SubString(1, CommaPos - 1);
16554 ServiceList.push_back(OneService);
16555 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
16559 ServiceList.push_back(InternalInput);
16560 InternalInput =
"";
16564 ServiceList.sort();
16565 ServiceList.unique();
16566 NumTrainsAtLoc = ServiceList.size();
16567 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
16569 Output = Output + *SLIt +
",";
16571 if(Output.Length() > 0)
16573 Output = Output.SubString(1, Output.Length() - 1);
16586 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
16588 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
16593 bool LocFound =
false;
16594 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
16596 TDateTime FirstServiceTime;
16599 int Ref1Target = 0, Ref1Count = 0;
16600 int SlashPos = Ref1.Pos(
'/');
16603 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
16604 Ref1 = Ref1.SubString(1, SlashPos - 1);
16606 int Ref2Target = 0, Ref2Count = 0;
16607 SlashPos = Ref2.Pos(
'/');
16610 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
16611 Ref2 = Ref2.SubString(1, SlashPos - 1);
16614 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
16616 if((*ListPtr1) == Location)
16618 LocPtr1 = ListPtr1;
16621 if(ListPtr1->SubString(1, 3) ==
"%%%")
16623 AnsiString CDTTime = ListPtr1->SubString(4, 5);
16628 FirstServiceTime = TDateTime(-1);
16629 bool BreakFlag =
false;
16632 if(TDVIt->ServiceReference == Ref1)
16634 if(Ref1Target > Ref1Count)
16639 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
16640 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
16644 FirstServiceTime = AVIt->EventTime;
16650 FirstServiceTime = AVIt->ArrivalTime;
16656 FirstServiceTime = AVIt->DepartureTime;
16667 if(IncMinutes == -1)
16669 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16671 if(FirstServiceTime == TDateTime(-1))
16673 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16677 if(!Arrival && (Time1 == CDTTime))
16682 if(Arrival && (Time1 == CDTTime))
16686 if(Time1 > CDTTime)
16691 if(Time1 < CDTTime)
16705 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
16707 if((*ListPtr2) == Location)
16709 LocPtr2 = ListPtr2;
16712 if(ListPtr2->SubString(1, 3) ==
"%%%")
16714 AnsiString CDTTime = ListPtr2->SubString(4, 5);
16719 FirstServiceTime = TDateTime(-1);
16720 bool BreakFlag =
false;
16723 if(TDVIt->ServiceReference == Ref2)
16725 if(Ref2Target > Ref2Count)
16730 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
16731 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
16735 FirstServiceTime = AVIt->EventTime;
16741 FirstServiceTime = AVIt->ArrivalTime;
16747 FirstServiceTime = AVIt->DepartureTime;
16758 if(IncMinutes == -1)
16760 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16762 if(FirstServiceTime == TDateTime(-1))
16764 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
16768 if(!Arrival && (Time2 == CDTTime))
16773 if(Arrival && (Time2 == CDTTime))
16777 if(Time2 > CDTTime)
16782 if(Time2 < CDTTime)
16798 LP1 = List1.begin();
16800 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
16802 if(ListPtr1 == List1.begin())
16806 if(ListPtr1->SubString(1, 3) ==
"%%%")
16813 LP2 = List2.begin();
16815 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
16817 if(ListPtr2 == List2.begin())
16821 if(ListPtr2->SubString(1, 3) ==
"%%%")
16831 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
16833 if(ListPtr1 == LocPtr1)
16837 if(ListPtr1->SubString(1, 3) ==
"%%%")
16841 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
16843 if(ListPtr2 == LocPtr2)
16847 if(ListPtr2->SubString(1, 3) ==
"%%%")
16851 if((*ListPtr1) == (*ListPtr2))
16864 LP1 = LocPtr1; LP1++;
16865 LP2 = LocPtr2; LP2++;
16866 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
16868 if(ListPtr1 == List1.end())
16872 if(ListPtr1->SubString(1, 3) ==
"%%%")
16876 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
16878 if(ListPtr2 == List2.end())
16882 if(ListPtr2->SubString(1, 3) ==
"%%%")
16886 if((*ListPtr1) == (*ListPtr2))
16903 if(ExitList.empty())
16909 if(StartName ==
"")
16911 if(ExitList.size() == 1)
16915 return " at " + ID;
16932 return " at " + StartName;
16971 AnsiString FormatStr =
"####0.0";
16972 AnsiString AvLateArrMins =
"";
16973 AnsiString AvEarlyArrMins =
"";
16974 AnsiString AvLatePassMins =
"";
16975 AnsiString AvEarlyPassMins =
"";
16976 AnsiString AvLateDepMins =
"";
16989 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
16990 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
16998 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
17000 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
17005 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
17007 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
17012 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
17017 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
17019 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
17021 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
17024 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
17026 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
17028 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
17031 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
17033 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
17036 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
17038 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
17040 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
17042 TDateTime TempExcessLCDownTime;
17053 if(TempExcessLCDownTime > TDateTime(0))
17059 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
17062 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
17065 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
17067 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
17085 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
17087 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
17093 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
17097 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
17101 AnsiString AvLateMinsLocsNotReached =
"";
17107 if(LocsNotReached > 0)
17110 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
17114 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
17116 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
17124 PerfFile <<
Derailments <<
" derailments" <<
'\n';
17126 PerfFile <<
Derailments <<
" derailment" <<
'\n';
17133 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
17135 bool DerailSPADFlag =
false, CrashFlag =
false;
17137 int OverallScorePercent = 100;
17139 double TotLateMinsFactor = 1;
17140 double MissedStopAndSPADRiskFactor = 1;
17141 double NetNegFactor = 1;
17150 OverallScorePercent = 5;
17151 DerailSPADFlag =
true;
17155 OverallScorePercent = 0;
17158 if(OverallScorePercent == 100)
17162 TotLateMinsFactor =
17170 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
17172 OverallScorePercent = 100 * NetNegFactor;
17175 if((TotArrDep > 0) || DerailSPADFlag || CrashFlag)
17178 AnsiString OneFailureString =
", though the failure would account for some poor performance";
17179 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
17180 AnsiString AddedString =
"";
17182 AddedString = OneFailureString;
17184 AddedString = TwoOrMoreFailureString;
17185 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
17186 AnsiString Rating =
"";
17187 if(OverallScorePercent == 100)
17188 Rating =
"Perfect!";
17189 else if(OverallScorePercent >= 95)
17190 Rating =
"Excellent";
17191 else if(OverallScorePercent >= 90)
17192 Rating =
"Very good";
17193 else if(OverallScorePercent >= 80)
17195 else if(OverallScorePercent >= 70)
17197 else if(OverallScorePercent >= 60)
17198 Rating =
"Unacceptable" + AddedString;
17199 else if(OverallScorePercent >= 50)
17200 Rating =
"Poor" + AddedString;
17201 else if(OverallScorePercent >= 40)
17202 Rating =
"Bad" + AddedString;
17203 else if(OverallScorePercent >= 30)
17204 Rating =
"Very bad" + AddedString;
17205 else if(OverallScorePercent >= 20)
17206 Rating =
"Terrible" + AddedString;
17207 else if(OverallScorePercent >= 10)
17208 Rating =
"Appalling" + AddedString;
17209 else if(OverallScorePercent >= 5)
17212 Rating =
"Disastrous - potential loss of life";
17215 Rating =
"Dire" + AddedString;
17217 else if(OverallScorePercent < 5)
17220 Rating =
"Catastrophic - loss of life";
17222 Rating =
"Abysmal";
17224 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
17228 PerfFile <<
"\nThere were no timetabled departures or arrivals so there is insufficient information to provide a performance score or rating" <<
'\n';
17230 PerfFile <<
'\n' <<
"***************************************";
17239 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17289 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17321 int IncrementalMinutes = 0;
17333 bool TrainOperatingFlag =
false;
17338 TrainOperatingFlag =
true;
17342 if(TrainOperatingFlag)
17349 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
17394 AnsiString HeadCode;
17398 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17402 HCandTrainPosParam.first = HeadCode;
17403 HCandTrainPosParam.second = TrainID;
17405 if((TimeToAct >= 0) && (TimeToAct < 59.9))
17408 OpTimeToActMultiMapEntry.first = TimeToAct;
17409 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
17439 float TimeToAct = 0;
17440 int DistanceToRedSignal = 0;
17443 ContinuationEntryVecPosVector.clear();
17444 bool LaterTrain =
false;
17448 LaterTrain =
false;
17449 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
17460 if(!ContinuationEntryVecPosVector.empty())
17462 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
17464 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
17466 LaterTrain =
true; ;
17477 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
17478 AnsiString HeadCode = CTEIt->second.HeadCode;
17479 float CurrentStopTime;
17480 float LaterStopTime;
17481 float RecoverableTime;
17484 bool SigControlAndCanPassRedSignal =
false;
17488 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(1),
17490 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed);
17493 if(AvTrackSpeed < 30)
17495 if(DistanceToRedSignal == -1)
17501 int Speed = AvTrackSpeed;
17502 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
17503 if(AvTrackSpeed > MaxSpeed)
17505 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(1).SignallerControl)
17508 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
17511 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
17516 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
17517 TimeToAct += MinsBefEnter;
17520 HCandTrainPosParam.first = HeadCode;
17521 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
17524 if(TimeToAct < 59.9)
17526 OpTimeToActMultiMapEntry.first = TimeToAct;
17527 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
17539 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
17540 float &RecoverableTime,
int &AvTrackSpeed)
17549 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
17550 int DistanceToRedSignal = 0;
17551 int CumTrackSpeed = 0;
17553 int TrackSpeedCount = 0;
17564 int CurrentElement = TrackVectorPosition;
17565 int CurrentEntryPos = TrackVectorPositionEntryPos;
17570 CurrentStopTime = 0;
17572 RecoverableTime = 0;
17573 if(CurrentElement == -1)
17578 int CurrentExitPos;
17583 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
17586 CurrentExitPos = 1;
17588 CurrentExitPos = 3;
17591 CurrentExitPos = 0;
17624 CurrentStopTime = float(TimeToDepart);
17631 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
17642 else if(SigControlAndCanPassRedSignal)
17647 if((NextEntryPos == 0) || (NextEntryPos == 2))
17661 CurrentElement = NextElement;
17662 CurrentEntryPos = NextEntryPos;
17663 CurrentExitPos = NextExitPos;
17675 int LaterStopNumber = 0;
17679 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
17688 if(CurrentEntryPos > 1)
17708 bool StopRequired =
false;
17726 int TrainOnElement;
17733 if(CurrentEntryPos > 1)
17738 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
17748 double StopTimeDouble;
17759 if(StopTimeDouble < 0.5)
17760 StopTimeDouble = 0.5;
17763 LaterStopTime += float(StopTimeDouble);
17764 RecoverableTime += StopTimeDouble - 0.5;
17765 if((LaterStopNumber == 1) && (TrainID > -1))
17771 if((AVPtr + 1)->FormatType ==
TimeLoc)
17775 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
17777 if(StopTimeDouble < 0.5)
17778 StopTimeDouble = 0.5;
17780 LaterStopTime += float(StopTimeDouble);
17781 RecoverableTime += StopTimeDouble - 0.5;
17782 if((LaterStopNumber == 1) && (TrainID > -1))
17797 if(NextElement == -1)
17806 if((NextEntryPos == 0) || (NextEntryPos == 2))
17820 CurrentElement = NextElement;
17821 CurrentEntryPos = NextEntryPos;
17822 CurrentExitPos = NextExitPos;
17826 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
17841 float MaxAllowableSpeed;
17843 if(TrackSpeedCount > 0)
17844 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
17847 if(CurrentEntryPos > 1)
17857 float KmPerLocationStop;
17859 if(LaterStopNumber > 0)
17861 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
17862 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
17866 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
17870 if(AvTrackSpeed > MaxAllowableSpeed)
17871 AvTrackSpeed = MaxAllowableSpeed;
17873 return DistanceToRedSignal;